package com.jty.module_main.ui.fragment

import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.annotation.RequiresApi
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import com.alibaba.android.arouter.facade.annotation.Route
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.ScreenUtils
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.czl.lib_base.config.AppConstants
import com.gyf.immersionbar.ImmersionBar
import com.jty.lib_base.base.BaseBean
import com.jty.lib_base.base.BaseFragment
import com.jty.lib_base.data.bean.OssParams
import com.jty.lib_base.event.LiveBusCenter
import com.jty.lib_base.extension.ApiSubscriptHelper
import com.jty.lib_base.oss.UploadOss
import com.jty.lib_base.room.AppDatabase
import com.jty.lib_base.room.bean.GridNoSubmit
import com.jty.lib_base.room.bean.GridPicture
import com.jty.lib_base.tsdBlePen.CommitOfflineReq
import com.jty.lib_base.tsdBlePen.TsdPenUtil
import com.jty.lib_base.tsdBlePen.TsdService
import com.jty.lib_base.utils.*
import com.jty.lib_base.widget.graffiti.GraffitiOnTouchGestureListener
import com.jty.lib_base.widget.graffiti.GraffitiTouchDetector
import com.jty.lib_base.widget.graffiti.GraffitiView
import com.jty.lib_base.widget.graffiti.IGraffitiTouchDetector
import com.jty.module_main.BR
import com.jty.module_main.R
import com.jty.module_main.adapter.NoteBookAdapter
import com.jty.module_main.databinding.MainFragmentHomeBinding
import com.jty.module_main.viewmodel.NoteViewModel
import com.kongzue.dialogx.dialogs.WaitDialog
import com.orhanobut.logger.Logger
import com.scwang.smart.refresh.layout.api.RefreshLayout
import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener
import com.tstudy.blepenlib.BlePenStreamManager
import com.tstudy.blepenlib.data.BleDevice
import com.tstudy.blepenlib.data.CoordinateInfo
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.RequestBody
import java.io.File
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.TimeUnit


/**
 * author: zhouyh
 * created on: 2021/9/18 8:59 下午
 * description:首页
 */
@Route(path = AppConstants.Router.Main.F_HOME)
class HomeFragment : BaseFragment<MainFragmentHomeBinding, NoteViewModel>() {

    lateinit var mNoteBookAdapter: NoteBookAdapter
    private val mQDots: ConcurrentLinkedQueue<CoordinateInfo> = ConcurrentLinkedQueue<CoordinateInfo>()
    private var mCurDot: CoordinateInfo? = null
    private var mGridPicture: GridPicture? = null
    @Volatile private var  mIsLoadingImg = false
    private var mGraffitiView: GraffitiView? = null
    private var mGraffitiTouchGestureListener: GraffitiOnTouchGestureListener? = null
    private var mDoodleBitmap: Bitmap? = null
    private var mTemp_x = 0f //暂存转换后的坐标
    private var mTemp_y = 0f
    private val mGridPictureList = mutableListOf<GridPicture>()
    private val mCommitOfflineReqS = mutableListOf<CommitOfflineReq>()
    private var mIsSubmit = false
    private var mIsOffEnding = false
    private var uploadCount = 0
    private var mPrevImgPath = ""
    private var mCurImgPath = ""
    private var mMaxSort = 0
    private var mScale = 1.0f

    private val mTsdListener: TsdService.OnDataReceiveListener = object : TsdService.OnDataReceiveListener {
        override fun onErrTsdPen(code: Int, msg: String?) {

        }

        override fun onOffDrawEnd() {
            mIsOffEnding = false
            if(mQDots.isNullOrEmpty()) {
                if (mGraffitiView != null) {
                    mIsSubmit = true
                    savePic()
                } else if(mGridPictureList.size > 0) {
                    //离线没有涂鸦，但是有没有上传成功的数据
                    mIsSubmit = true
                    uploadImg()
                } else {
                    isFromTeachFinish()
                }
            } else {
                mIsOffEnding = true
            }


        }

        override fun onRefreshScan(isScaning: Boolean) {
        }

        override fun onAddDevice(bleDevice: BleDevice?) {
        }

        override fun onPenConnectStatus(code: Int, bleDevice: BleDevice?) {
            if (code == TsdService.CONN_PEN_START) {
                //DialogXUtil.waitDialogShow("正在连接中...");
            } else if (code == TsdService.CONN_PEN_FAIL) {
                viewModel.setmIsPenConnect(false)
            } else if (code == TsdService.CONN_PEN_SUCCESS) {
                viewModel.setmIsPenConnect(true)
                viewModel.setmPenMac(mTsdServiceBinder?.on_getmBleDevice()!!.mac)
            } else if (code == TsdService.CONN_PEN_DIS) {
                viewModel.setmIsPenConnect(false)
            }
        }

        override fun onGetPenInfo(batteryPercent: Int, memoryPercent: Int, memoryByteNum: Int) {
            viewModel.setPenInfo(batteryPercent, memoryPercent, memoryByteNum)

            binding.tvDl.setTextColor(Color.parseColor("#ff999999"))
            if (batteryPercent < 20) {
                binding.ivDl.setImageResource(R.drawable.base_dl_0)
                binding.tvDl.setTextColor(Color.parseColor("#FF4A55"))
            } else if (batteryPercent < 40) {
                binding.ivDl.setImageResource(R.drawable.base_dl_1)
            } else if (batteryPercent < 60) {
                binding.ivDl.setImageResource(R.drawable.base_dl_2)
            } else if (batteryPercent < 80) {
                binding.ivDl.setImageResource(R.drawable.base_dl_3)
            } else {
                binding.ivDl.setImageResource(R.drawable.base_dl_4)
            }
        }

        override fun onCoordDraw(coordinateInfo: CoordinateInfo?) {
            mQDots.offer(coordinateInfo)
            pollDots()
        }

        override fun onFinish() {
        }
    }


    override fun onSupportVisible() {
        ImmersionBar.with(this).fitsSystemWindows(true)
            .statusBarDarkFont(!DayModeUtil.isNightMode(requireContext())).init()
    }

    override fun initContentView(): Int {
        return R.layout.main_fragment_home
    }

    override fun initVariableId(): Int {
        return BR.viewModel
    }


    override fun useBaseLayout(): Boolean {
        return true
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        showLoadingStatePage()
    }


    override fun getIsBindTsdService(): Boolean {
        return true
    }

    override fun getTsdServiceDataReceiveListener(): TsdService.OnDataReceiveListener? {
        return mTsdListener
    }

    override fun setTsdServiceConnected() {
        super.setTsdServiceConnected()

        if (mTsdServiceBinder!!.on_getPenIsConnect()) {
            //setRealtimeMode() //为了在作答界面，自动连接蓝牙，有离线数据的情况
            //refreshShowView(isConnect)

            viewModel.setmIsPenConnect(true)
            BlePenStreamManager.getInstance().getPenInfo()
            viewModel.setmPenMac(mTsdServiceBinder?.on_getmBleDevice()!!.mac)

        } else {
            viewModel.setmIsPenConnect(false)
            //mListener.on_ct_startScan()
        }
    }

    override fun initData() {
        super.initData()
        //禁止息屏
        requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        mNoteBookAdapter = NoteBookAdapter(requireContext())
        binding.rvV.setLayoutManager(WrapContentLinearLayoutManager(this.activity, LinearLayoutManager.VERTICAL, false))
        binding.rvV.setItemAnimator(DefaultItemAnimator())
        binding.rvV.setAdapter(mNoteBookAdapter)
        mNoteBookAdapter.setOnItemClickListener(object : NoteBookAdapter.OnItemClickListener{
            override fun onItemClick(view: View, position: Int, id: Int, lastIndex: Int, bookName:String, totalPage: Int) {
                startContainerActivity(AppConstants.Router.Main.F_PREVIEW, Bundle().apply {
                    putInt("id", id)
                    putInt("lastIndex", lastIndex)
                    putInt("totalPage", totalPage)
                    putString("bookName", bookName)
                })
            }
        })

        //viewModel.pageBybookNote(1)
        initSmartRefresh()

        //startService(Intent(this, TsdService::class.java))

        //val isConnect = mTsdServiceBinder?.on_getmBleDevice() != null
    }

    override fun onDestroyView() {
        //禁止息屏
        requireActivity().window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        super.onDestroyView()
    }

    override fun onResume() {
        super.onResume()

        viewModel.pageBybookNote(1)
    }

    private fun initSmartRefresh() {
        binding.srlRefresh.setOnRefreshLoadMoreListener(object : OnRefreshLoadMoreListener {
            override fun onRefresh(refreshLayout: RefreshLayout) {
                Logger.i("---下拉刷新")
                viewModel.pageBybookNote(1)
            }

            override fun onLoadMore(refreshLayout: RefreshLayout) {
                Logger.i("---加载更多")
                if (viewModel.mPageBean.value!!.pages > viewModel.mPageBean.value!!.current) {
                    viewModel.pageBybookNote(viewModel.mPageBean.value!!.current + 1)
                } else {
                    refreshLayout.getLayout().postDelayed(Runnable {
                        refreshLayout.finishLoadMoreWithNoMoreData() //将不会再次触发加载更多事件
                    }, 1000)
                }
            }
        })
        //srl_refresh.setRefreshHeader(ClassicsHeader(activity))
        //srl_refresh.setRefreshFooter(ClassicsFooter(activity))
    }

    fun resetNoMoreData() {
        if (binding.srlRefresh != null) {
            binding.srlRefresh.resetNoMoreData() //去除没有更多数据状态
        }
    }

    fun finishSmart(cur: Int) {
        if (cur == 1) {
            resetNoMoreData()
            //mStudentExamList.clear()
        }
        if (binding.srlRefresh != null) {
            binding.srlRefresh.getLayout().postDelayed(Runnable {
                if (binding.srlRefresh != null) {
                    binding.srlRefresh.finishRefresh()
                    binding.srlRefresh.finishLoadMore()
                }
            }, 500)
        }
    }

    override fun initViewObservable() {
        super.initViewObservable()
        LiveBusCenter.observePenIsConnectEvent(this){
        }


        viewModel.mPageBean.observe(this) {
            mNoteBookAdapter.refreshData(it.records)
        }

        viewModel.uc.finishSmart.observe(this) {
            finishSmart(it)
        }

        viewModel.uc.clickPenConnect.observe(this) {
            PermissionUtil.reqLocation(activity = requireActivity(), callback = { allGranted, _, _->
                if (allGranted){
                    mTsdServiceBinder?.on_clickConnect()
                }
            })
        }

        viewModel.uc.clickPenDisConnect.observe(this) {
            val bleDevice = mTsdServiceBinder?.on_getmBleDevice()
            if (bleDevice != null) {
                if (BlePenStreamManager.getInstance().isConnected(bleDevice)) {
                    //如果当前设备已连接，断开连接。
                    BlePenStreamManager.getInstance().disconnect(bleDevice)
                }
            }
        }

    }
    private fun isFromTeachFinish(){
        mTsdServiceBinder?.let {
            if(it.on_getmIsFromTeach()) {
                it.on_setmIsFromTeach(false)
                requireActivity().finish()
            }
            it.on_setmDisDotOnOff(2)
        }
    }

    private fun pollDots() {
        if(mIsLoadingImg) {
            return
        }
        if(mQDots.isNullOrEmpty()) {
            if(mIsOffEnding) {
                mIsOffEnding = false
                if(mGraffitiView != null) {
                    mIsSubmit = true
                    savePic()
                } else if(mGridPictureList.size > 0) {
                    //离线没有涂鸦，但是有没有上传成功的数据
                    mIsSubmit = true
                    uploadImg()
                }else {
                    isFromTeachFinish()
                }
            }
            return
        }
        mCurDot = mQDots.poll()
        if(mCurDot == null) {
            return
        }
        if(mGridPicture == null || mCurDot!!.pageAddress != mGridPicture!!.pageserial) {
            //找图片
            val gridPicture = AppDatabase.getInstance().gridPictureDao().queryByPageserial(mCurDot!!.pageAddress)
            if(gridPicture == null) {
                pollDots()
                return
            }
            gridPicture?.let {
                if(mGridPictureList.isEmpty()) {
                    val list =  AppDatabase.getInstance().gridNoSubmitDao().getAll()
                    if(list.isNotEmpty()) {
                        Logger.e("-----自动保存的个数：${list.size}")
                        for(value in list) {
                            val screenWidth = ScreenUtils.getScreenWidth()
                            val scale = screenWidth * TsdService.IMG_SCALE / value.width

                            mGridPictureList.add(GridPicture(value.id, value.pageserial, value.pageNumber, value.pictureName, value.pictureUrl, value.width, value.height, scale, null))
                        }
                    }
                    mMaxSort = AppDatabase.getInstance().gridNoSubmitDao().getMaxSort()
                }
                for((index, value) in mGridPictureList.withIndex()) {
                    if(value.pageserial == it.pageserial) {
                        mGridPictureList.remove(value)
                        break;
                    }
                }
                mGridPictureList.add(gridPicture)
                //viewModel.refreshLastWrite(gridPicture)

                mMaxSort++
                var gridNoSubmit = AppDatabase.getInstance().gridNoSubmitDao().queryByPageserial(it.pageserial)
                if(gridNoSubmit == null) {
                    gridNoSubmit = GridNoSubmit(it.id.toLong(), it.pageserial, it.pageNumber, it.pictureName, it.pictureUrl, it.width, it.height, it.bookNoteId!!.toInt(), mMaxSort)
                    AppDatabase.getInstance().gridNoSubmitDao().insertAll(gridNoSubmit)
                } else {
                    gridNoSubmit.sort = mMaxSort
                    AppDatabase.getInstance().gridNoSubmitDao().updateGridNoSubmit(gridNoSubmit)
                }


                mGridPicture?.let{
                    mPrevImgPath = getPicFilePath(
                        viewModel.model.getUserId()!!,
                        "gridPicture",
                        "" + PageserialUtils.pageserialToFileName(it.pageserial),
                        ""
                    )!!
                }


                mCurImgPath = getPicFilePath(
                    viewModel.model.getUserId()!!,
                    "gridPicture",
                    "" + PageserialUtils.pageserialToFileName(gridPicture!!.pageserial),
                    ""
                )!!

                mGridPicture = gridPicture
                mIsLoadingImg = true
                if(mGraffitiView == null) changePic() else savePic()
            }
        } else {
            //去绘制
            drawTrack_real(mCurDot!!)
        }
    }
    private fun changePic() {
        if(mCurDot == null) {
            mIsLoadingImg = false
            return
        }
        mGridPicture?.let{
            val screenWidth = ScreenUtils.getScreenWidth()
            mScale = screenWidth * TsdService.IMG_SCALE / it.width
            val realWidth = it.width * mScale
            val realHeight = it.height * mScale
            Logger.i("屏幕宽：$screenWidth, 图片的高：${it.width}, scale: $mScale，转换宽：${realWidth}, 转换高: $realHeight")
            downLoadImg(realWidth, realHeight)
        }

    }

    private fun downLoadImg(realWidth: Float, realHeight: Float) {
        val imgFile: File = File(mCurImgPath)
        if(!imgFile.exists()) {
            Logger.e("图片不存在，出错了")
            mGridPicture = null
            mIsLoadingImg = false
            pollDots()
            return
        }
        Glide.with(this).asBitmap().load(mCurImgPath).skipMemoryCache(true)
            .diskCacheStrategy(DiskCacheStrategy.NONE)
            .override(realWidth.toInt(), realHeight.toInt())
            .into(object : CustomTarget<Bitmap?>() {
                override fun onResourceReady(
                    resource: Bitmap,
                    transition: Transition<in Bitmap?>?
                ) {
                    Logger.e("m1:Glde图片-成功  = " + mCurImgPath)
                    mDoodleBitmap = resource
                    initGraffitiData()
                }

                override fun onLoadFailed(errorDrawable: Drawable?) {
                    super.onLoadFailed(errorDrawable)
                    Logger.e("m1:Glde图片-失败  = " + mCurImgPath)
                    mIsLoadingImg = false
                    pollDots()
                }

                override fun onLoadCleared(placeholder: Drawable?) {}
            })
    }

    private fun initGraffitiData() {
        binding.flDoodle.removeAllViews()

        mGraffitiView = GraffitiView(
            this.activity,
            mDoodleBitmap,
            null,
            false,
            false,
            object : GraffitiView.IGraffitiViewListener {
                override fun onSaved(bitmaps: MutableList<Bitmap>?) {
                    Logger.i("m1:涂鸦保存成功")
                    Observable.create<Int> { emitter ->
                        saveBitmap(bitmaps!![0], if(mIsSubmit)mCurImgPath else mPrevImgPath)
                        emitter.onNext(1)
                        emitter.onComplete()
                    }.compose(bindToLifecycle()).subscribeOn(Schedulers.newThread())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(object : Observer<Int?> {
                            override fun onSubscribe(d: Disposable) {
                            }

                            override fun onNext(t: Int) {
                                if(mIsSubmit) {
                                    mIsLoadingImg = false
                                    uploadImg()
                                } else {
                                    changePic()
                                }
                            }

                            override fun onError(e: Throwable) {
                            }

                            override fun onComplete() {
                            }
                        })
                }
            })
        mGraffitiTouchGestureListener = GraffitiOnTouchGestureListener(
            mGraffitiView,
            object : GraffitiOnTouchGestureListener.IGraffitiOnTouchGestureListener {
                override fun onTest() {
                }

                override fun onLongPress(e: MotionEvent?) {
                }

                override fun onCallScroll(
                    e1: MotionEvent?,
                    e2: MotionEvent?,
                    distanceX: Float,
                    distanceY: Float
                ) {
                    //Logger.i("m1:滚动手指：distanceX: $distanceX, distanceY:$distanceY")
                }

            })
        val detector: IGraffitiTouchDetector =
            GraffitiTouchDetector(this.activity, mGraffitiTouchGestureListener)
        mGraffitiView?.setDefaultTouchDetector(detector)
        mGraffitiTouchGestureListener?.setSupportScale(false) //禁止放大缩小
        setSupportDoodle(false)
        setSupportTrans(false)
        mGraffitiTouchGestureListener?.setTouchType(GraffitiOnTouchGestureListener.TOUCH_TYPE_ALL)


        //mGraffitiView.setStartXy(true);
        mGraffitiView?.setColor(Color.BLACK)
        mGraffitiView?.setIsDrawableOutside(false)
        mGraffitiView?.setSize(2f)
        binding.flDoodle.addView(
            mGraffitiView,
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        )
        delayToDot(300)
    }

    private fun setSupportDoodle(isSupport: Boolean) {
        mGraffitiTouchGestureListener?.setSupportGraffiti(isSupport)
    }

    private fun setSupportTrans(isSupport: Boolean) {
        mGraffitiTouchGestureListener?.setSupportTrans(isSupport)
    }

    private fun delayToDot(time: Int) {
        Observable.timer(time.toLong(), TimeUnit.MILLISECONDS)
            .observeOn(AndroidSchedulers.mainThread())
            .compose(bindToLifecycle())
            .subscribe(object : Observer<Long> {
                override fun onSubscribe(d: Disposable) {}
                override fun onNext(aLong: Long) {
                    mIsLoadingImg = false
                    drawTrack_real(mCurDot!!)
                }

                override fun onError(e: Throwable) {}
                override fun onComplete() {}
            })
    }

    private fun drawTrack_real(dot: CoordinateInfo) {
        mTemp_x = TsdPenUtil.getRealX(dot.coordX.toFloat(), mGridPicture!!.width) * mScale
        mTemp_y = TsdPenUtil.getRealY(dot.coordY.toFloat(), mGridPicture!!.height) * mScale
        if (dot.state == TsdService.PEN_DOWN_MESSAGE) {
            mGraffitiTouchGestureListener!!.r_onDown(mTemp_x, mTemp_y)
            mGraffitiTouchGestureListener!!.r_onScrollBegin(mTemp_x, mTemp_y)
        } else if (dot.state == TsdService.PEN_COODINAT_MESSAGE) {
            mGraffitiTouchGestureListener!!.r_onScroll(mTemp_x, mTemp_y)
        } else if (dot.state == TsdService.PEN_UP_MESSAGE) {
            mGraffitiTouchGestureListener!!.r_onScrollEnd(mTemp_x, mTemp_y)
        }

        pollDots()
    }

    private fun savePic() {
        if (mGraffitiView != null) {
            mGraffitiView!!.save()
        }
    }

    private fun uploadImg() {
        if(mGridPictureList.size == 0) {
            mIsSubmit = false
            isFromTeachFinish()
            return
        }
        mCommitOfflineReqS.clear()
        uploadCount = 0
        WaitDialog.show("正在上传数据")
        uploadImg_http()
    }
    private fun uploadImg_http() {
        if(uploadCount != mGridPictureList.size) {
            val imgPath= getPicFilePath(
                viewModel.model.getUserId()!!,
                "gridPicture",
                "" + PageserialUtils.pageserialToFileName(mGridPictureList.get(uploadCount).pageserial),
                ""
            )
            if(!File(imgPath).exists()) {
                WaitDialog.dismiss()
                mIsSubmit = false
                isFromTeachFinish()
                return
            }
            val uploadPath = "${viewModel.model.getUserId()!!}_${PageserialUtils.pageserialToFileName(mGridPictureList.get(uploadCount).pageserial)}_${System.currentTimeMillis()}.png"
            UploadOss.getInstance()?.upload2OSS(uploadPath, imgPath!!, onUploadListener, null)
        } else {
            commitTeacherBookNote()
        }
    }

    private fun commitTeacherBookNote() {
        val requestBody = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),
            GsonUtils.toJson(mCommitOfflineReqS))

        viewModel.model.apply {
            commitTeacherBookNote(requestBody)
                .compose(RxThreadHelper.rxSchedulerHelper(viewModel))
                .subscribe(object : ApiSubscriptHelper<BaseBean<Any?>>() {
                    override fun onResult(t: BaseBean<Any?>) {
                        //Logger.e(t.toString())
                        WaitDialog.dismiss()
                        mIsSubmit = false
                        if (t.code == 0) {
                            showNormalToast("上传成功")



                            mQDots.clear()
                            mCurDot = null
                            mGridPicture = null
                            mGraffitiView = null
                            mGridPictureList.clear()
                            mCommitOfflineReqS.clear()
                            mPrevImgPath = ""
                            mCurImgPath = ""

                            AppDatabase.getInstance().gridNoSubmitDao().deleteAll()
                        }
                        isFromTeachFinish()
                        viewModel.pageBybookNote(1)
                    }

                    override fun onFailed(msg: String?) {
                        WaitDialog.dismiss()
                        showNormalToast(msg)
                        mIsSubmit = false
                        isFromTeachFinish()
                    }
                })
        }
    }

    val onUploadListener = object : UploadOss.OnUploadListener{
        override fun uploadSuccess(uploadFile: String?, localFile: String, ossParams: OssParams?, ): String? {
            mCommitOfflineReqS.add(CommitOfflineReq(uploadFile!!, mGridPictureList.get(uploadCount).pageserial))
            uploadCount++
            uploadImg_http()
            return null
        }

        override fun uploadFail(
            uploadFile: String?,
            localFile: String,
            ossParams: OssParams?,
        ): String? {
            uploadCount = 0
            WaitDialog.dismiss()
            mIsSubmit = false
            isFromTeachFinish()
            return null
        }

    }
}